Note: this is essentially a solution file! If you’d like to work through the document without all the code provided download this .Rmd file (link warning! clicking the link will auto download the .Rmd).
# For saving plots to SVG
library(svglite)
# For easy plotting of shapes
library(plotrix)
# For use of "perlin noise"
library(ambient)
Let’s start with a regular R plot. Plot y by
x. Before we can plot x and y we
need an x and a y to plot! Below makes some
random data using the runif() function.
runif (short for “random uniform”) pulls random values
from a “uniform” distribution (uniform here means that
all values are equally likely, the prbability of each value is
uniform).
x <- runif(n = 32, min = -1, max = 11)
y <- runif(n = 32, min = 2, max = 11)
plot(x, y)
It’s snowing!!
Get them pesky axes out of there….
plot(x,
y,
xlab = "", # no x axis label
ylab = "", # no y axis label
axes = FALSE, # turn off axes
frame.plot = TRUE, # turn of the outline around the plot
)
Let’s manually control the axes limits so that the snow isn’t so close to the bottom of the frame.
plot(x,
y,
xlim = c(0, 10),
ylim = c(0, 10),
xlab = "", # no x axis label
ylab = "", # no y axis label
axes = FALSE, # turn off axes
frame.plot = TRUE, # turn of the outline around the plot
)
Let’s add in some ground! Flat ground is boring… what’s a mathy way to make it look like we’ve got a hilltop?
Work on it by itself without the snow to mix things up.
\[y = -0.04 \cdot (x - 4)^2 + 2\]
# don't modify `x`
x <- -1:11
# make a `y` using `x` to make our hilltop
y <- -0.04 * (x - 4)^2 + 2
# don't modify this plot code
plot(x, y, type = "l", xlim = c(0, 10), ylim = c(0, 10))
To combine this and our snow we can’t use plot(). We
have two separate sets of xs & ys to draw
and if we use plot() twice it will make two separate
pictures. We can use lines() to draw our hill after we use
plot() to create our canvas and draw the snow.
x <- runif(32, 0, 10)
y <- runif(32, 3, 10)
plot(x,
y,
xlim = c(1, 9),
ylim = c(0, 9),
xlab = "", # no x axis label
ylab = "", # no y axis label
axes = FALSE, # turn off axes
frame.plot = TRUE, # turn of the outline around the plot
)
x <- -1:11
y <- -0.04 * (x - 4)^2 + 2
lines(x, y)
What would make it look more like snow?…
Snow flakes shouldn’t all be the same size. What’s often beautiful about nature is the irregularities.
First lets just look at how to modify the size of the points.
🚨 Pause 🚨: we are professionals that can acknowledge homophones and push forward? … right?
The cex parameter of plot() stands for
“character expansion”. It is how we can set the percent size of points
or text in base R plots. By default it is set to 1 (100%) but if you
want points twice as big set it to 2 (200%) and if you want points half
as big set it to 0.5 (50%).
x <- runif(32, 0, 10)
y <- runif(32, 3, 10)
plot(x,
y,
cex = 0.4,
xlim = c(0, 10),
ylim = c(0, 10),
xlab = "", # no x axis label
ylab = "", # no y axis label
axes = FALSE, # turn off axes
frame.plot = TRUE, # turn of the outline around the plot
)
Ok I’ve had enough of this ugly code we’ve copy pasted. To re-use the code without it being so ugly we’ll package it up into a function.
This function will take our x, y,
cex and plot them just like we’ve been doing. The addition
I made was the use of points(), like lines()
this lets us draw to an existing canvas rather than creating a new
plot.
plot_snow <- function(x, y, cex = 1, new_plot = TRUE) {
if (new_plot) {
plot(
x,
y,
cex = cex,
xlim = c(0, 10),
ylim = c(0, 10),
xlab = "", # no x axis label
ylab = "", # no y axis label
axes = FALSE, # turn off axes
frame.plot = TRUE, # turn of the outline around the plot
)
} else {
points(x, y, cex = cex)
}
}
Use the function to plot 2 different sizes of snow to the same picture.
x <- runif(n = 10, min = 0, max = 10)
y <- runif(n = 10, min = 4, max = 10)
plot_snow(x, y, cex = 1, new_plot = TRUE)
x <- runif(n = 10, min = 0, max = 10)
y <- runif(n = 10, min = 4, max = 10)
plot_snow(x, y, cex = 0.3, new_plot = FALSE)
Ooooohhhhhh
Do that for a bunch of different sizes! To add randomness to the
scene, we could vary the n in runif() for the
different sizes.
sizes <- c(0.1, 0.2, 0.3, 0.5, 0.8, 1)
new_plot <- TRUE
for (size in sizes) {
x <- runif(n = 5, min = 0, max = 10)
y <- runif(n = 5, min = 4, max = 10)
plot_snow(x, y, cex = size, new_plot = new_plot)
new_plot <- FALSE
}
Get our hilltop back in here!
sizes <- c(0.1, 0.2, 0.3, 0.5, 0.8, 1)
new_plot <- TRUE
for (size in sizes) {
n_flakes <- round(runif(1, 3, 10))
x <- runif(n = n_flakes, min = 0, max = 10)
y <- runif(n = n_flakes, min = 4, max = 10)
plot_snow(x, y, cex = size, new_plot = new_plot)
new_plot <- FALSE
}
x <- -1:11
y <- -0.04 * (x - 4)^2 + 2
lines(x, y)
It needs something….
Do you want to… build… a… snowman… ?
Hear me out, I think it’ll be nice to pretend we haven’t made our beautimus landscape. Let’s make a snow man and then when he’s ready we’ll place him on the hill top.
Building pieces separately is usually a solid move, and if we do it with some foresight we should be able to adjust the size and location in the landscape nicely and maybe give our snow dude some friends (or do <a=href=“https://i.pinimg.com/736x/0d/37/5c/0d375ceda1f9ae440eb738c1472a845f.jpg” target=“_blank”>the back of SUV family stickers thing) the back of SUV family stickers thing{:target=“_blank”}).